
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

using Swaf;
using Swaf.BizObj;
using Swaf.BizRule;
using Swaf.Container;
using Swaf.Security;

namespace Syrinx
{
	public class FileSysBizRules : Syrinx.BaseBizRules
	{
		public IBizObjList getFileSysCaches(IApplication app, IRuleContext context)
		{
			FlexiMap m = new FlexiMap();
			m.put("companyId", ActiveCompanyId);
			IBizObjList caches = app.appData.get("DA.FileSys.GetCompanyCaches", m) as IBizObjList;
			return caches;
		}

		public void updateFileSysCache(IApplication app, IRuleContext context, IBizObj cacheInfo)
		{
            cacheInfo.put("companyId", ActiveCompanyId);
			if (cacheInfo.isNew)
				app.appData.put("DA.FileSys.AddCache", cacheInfo);
			else
				app.appData.put("DA.FileSys.UpdateCache", cacheInfo);
		}

		public void deleteFileSysCache(IApplication app, IRuleContext context, string cacheName)
		{
			FlexiMap m = new FlexiMap();
			m.put("cacheName", cacheName);
			m.put("companyId", ActiveCompanyId);
			app.appData.put("DA.FileSys.DeleteCache", m);
		}

		public IBizObjList getFileSysCacheAppFunctions(IApplication app, IRuleContext context, string specifierId)
		{
			try
			{
				FlexiMap m = new FlexiMap();
				if (specifierId == null)
					specifierId = "FileSysCacheAppFunctions";
				m.put("specifierId", specifierId);
				m.put("companyId", ActiveCompanyId);
				return (IBizObjList)app.appData.get("DA.FileSys.GetFileSysCacheAppFunctions", m);
			}
			catch (Exception e)
			{
				throw new BaseException("Error executing getArticleGroupAppFunctions bizRule.", e);
			}
		}

		//--------------------------------------------------------------------------------------------

		public IBizObjList getFileSysDirectories(IApplication app, IRuleContext context, IBizObj info)
		{
			IBizObjList directories = app.bizObjMgr.createList("FileSysDirectory");
            if (info != null)
            {
                string startPath = app.resMgr.resolve(Cmn.pathCombine("$BaseFileSysStore$", (string)ActiveCompany.get("shortName"), (string)info.get("cacheName")));
                DirectoryInfo rootDi = Directory.CreateDirectory(startPath);
                IBizObj rootDir = directories.insertNew();
                rootDir.put("name", "- root -");
                rootDir.put("cacheName", info.get("cacheName"));
                rootDir.put("fileCount", rootDi.GetFiles().Length);

                getChildDirectories(startPath, directories, startPath.Length, (string)info.get("cacheName"), 0);
            }
			return directories;
		}

		public IBizObj getFileSysDirectoryDetails(IApplication app, IRuleContext context, IBizObj info)
		{
			return null;
		}

		public void updateFileSysDirectory(IApplication app, IRuleContext context, IBizObj dirInfo)
		{
            string path = app.resMgr.resolve(Cmn.pathCombine("$BaseFileSysStore$", (string)ActiveCompany.get("shortName"), (string)dirInfo.get("cacheName"),
                ((string)dirInfo.get("keyName")).Replace(':', Path.DirectorySeparatorChar)));
            string newPath = app.resMgr.resolve(Cmn.pathCombine("$BaseFileSysStore$", (string)ActiveCompany.get("shortName"), (string)dirInfo.get("cacheName"),
                ((string)dirInfo.get("parentName")).Replace(':', Path.DirectorySeparatorChar), (string)dirInfo.get("name")));
            if (dirInfo.isNew)
            {
                DirectoryInfo d2 = new DirectoryInfo(newPath);
                if (!d2.Exists)
                    d2.Create();
                else
                    throw new BaseException("Directory already exists");
            }
            else
            {
                DirectoryInfo d = new DirectoryInfo(path);
                if (d.Exists)
                    d.MoveTo(newPath);
            }
        }

		public void deleteFileSysDirectory(IApplication app, IRuleContext context, IBizObj info)
		{
			DirectoryInfo di = new DirectoryInfo(app.resMgr.resolve(Cmn.pathCombine("$BaseFileSysStore$", (string)ActiveCompany.get("shortName"),
				(string)info.get("cacheName"), info.get("keyName").ToString().Replace(':', Path.DirectorySeparatorChar))));
			di.Delete();
		}

		protected IBizObjList getChildDirectories(string path, IBizObjList list, int pos, string cacheName, int curDepth)
		{
			DirectoryInfo di = new DirectoryInfo(path);
			curDepth++;
			foreach (DirectoryInfo childDir in di.GetDirectories())
			{
				IBizObj directory = list.insertNew();
				Swaf.BGuid.Guid pid = new Swaf.BGuid.Guid();
				string keyName = childDir.FullName.Substring(pos).Replace(Path.DirectorySeparatorChar, ':');
				int index = keyName.LastIndexOf(':');
				if (index != -1)
					directory.put("parentName", keyName.Substring(0, index));
				else
					directory.put("parentName", null);
				directory.put("name", childDir.Name);
				directory.put("keyName", keyName);
				directory.put("depth", curDepth);
				directory.put("cacheName", cacheName);
				directory.put("fileCount", childDir.GetFiles().Length);
				directory.clearDirtyFlags();
				directory.isNew = false;
				getChildDirectories(childDir.FullName, list, pos, cacheName, curDepth);
			}
			return list;
		}

		//--------------------------------------------------------------------------------------------
		
		public IBizObjList getFileSysFiles(IApplication app, IRuleContext context, IBizObj info)
		{
            IBizObjList fobjs = app.bizObjMgr.createList("FileSysFile");
			string parentName = info.get("baseDirectory").ToString().Replace(':', Path.DirectorySeparatorChar);
			string cacheName = (string)info.get("cacheName");
            DirectoryInfo di = new DirectoryInfo(app.resMgr.resolve(Cmn.pathCombine("$BaseFileSysStore$", (string)ActiveCompany.get("shortName"),
                cacheName, parentName)));
            FileInfo[] files = di.GetFiles();
            foreach (FileInfo f in files)
            {
                IBizObj fobj = fobjs.insertNew();
                fobj.put("id", f.Name);
                fobj.put("name", f.Name);
				fobj.put("cacheName", cacheName);
				fobj.put("parentName", parentName);
                fobj.put("dateCreated", f.CreationTimeUtc);
                fobj.put("size", f.Length);
				fobj.put("fileImageUrl", string.Format("/img/{0}/FsSize/FileTypeImages/{1}.image",
							ActiveCompany.get("settings.defaultMediaCatalogName"),
							f.Extension.Substring(1)));
				string shortName = (string)ActiveCompany.get("settings.sitePath");
				if(!Cmn.IsEmpty(shortName))
					shortName = "/" + shortName;
				fobj.put("fileUrl",  string.Format("/filesys{0}/{1}/{2}/{3}", shortName,cacheName, parentName, f.Name));
			}
			return fobjs;
		}

		public IBizObj getFileSysFileDetails(IApplication app, IRuleContext context, IBizObj info)
		{
			IBizObj obj = Application.currentApp.bizObjMgr.create("FileSysFile");
			string fullName = null;
			string cacheName = (string)info.get("cacheName");
			if (cacheName.CompareTo("_sitebackups") == 0)
				fullName = app.resMgr.resolve(Cmn.pathCombine("$BaseBackupStore$", (string)ActiveCompany.get("shortName"), (string)info.get("name")));
			else
				fullName = app.resMgr.resolve(Cmn.pathCombine("$BaseFileSysStore$", (string)ActiveCompany.get("shortName"), (string)info.get("cacheName"),
				((string)info.get("baseDirectory")).Replace(':', Path.DirectorySeparatorChar), (string)info.get("name")));

			FileInfo fi = new FileInfo(fullName);
			if ((bool)info.get("includeBinary"))
			{
				Stream fs = new FileStream(fullName, FileMode.Open, FileAccess.Read);
				MediaStream m = new MediaStream(Path.GetExtension(fullName), fs, fullName);
				obj.put("data", m);
			}
			obj.put("id", new Swaf.BGuid.Guid());
			obj.put("name", Path.GetFileName(fullName));
			obj.put("parentName", Path.GetDirectoryName(fullName));
			obj.put("dateCreated", fi.CreationTime);
			obj.put("cacheName", info.get("cacheName"));
			obj.put("fileImageUrl", string.Format("/img/{0}/FsSize/FileTypeImages/{1}.image",
						ActiveCompany.get("settings.defaultMediaCatalogName"),
						fi.Extension.Substring(1)));
			obj.put("size", fi.Length);
			//obj.put("type", m.MimeType);

			return obj;
		}

		public void updateFileSysFile(IApplication app, IRuleContext context, IBizObj file)
		{
            if (file != null && file.get("data") != null && !Cmn.IsEmpty(file.get("name")))
            {
                string fullName = app.resMgr.resolve(Cmn.pathCombine("$BaseFileSysStore$", (string)ActiveCompany.get("shortName"), (string)file.get("cacheName"),
                    ((string)file.get("parentName")).Replace(':', Path.DirectorySeparatorChar), (string)file.get("name")));
                Directory.CreateDirectory(Path.GetDirectoryName(fullName));
                FileInfo fi = new FileInfo(fullName);
                FileStream fs = fi.OpenWrite();
                Binary bin = (Binary)file.get("data");
                try
                {
                    byte[] imgBytes = bin.Bytes;
                    fs.Write(imgBytes, 0, imgBytes.Length);
                }
                finally
                {
                    fs.Dispose();
                    bin.Dispose();
                }
            }
		}

		public void moveFilesToDirectory(IApplication app, IRuleContext context, string newDir, IBizObjList files, string origDir, string cacheName)
		{
			foreach (IBizObj file in files)
			{
				string fullName = app.resMgr.resolve(Cmn.pathCombine("$BaseFileSysStore$", (string)ActiveCompany.get("shortName"), cacheName,
					origDir.Replace(':', Path.DirectorySeparatorChar), (string)file.get("name")));
				string newFullName = app.resMgr.resolve(Cmn.pathCombine("$BaseFileSysStore$", (string)ActiveCompany.get("shortName"), cacheName,
					newDir.Replace(':', Path.DirectorySeparatorChar), (string)file.get("name")));

				FileInfo fi = new FileInfo(fullName);
				fi.MoveTo(newFullName);
			}
		}

		public void deleteFileSysFiles(IApplication app, IRuleContext context, string origDir, IBizObjList files, string cacheName)
		{
			foreach (IBizObj file in files)
			{
				string fullName = app.resMgr.resolve(Cmn.pathCombine("$BaseFileSysStore$", (string)ActiveCompany.get("shortName"), cacheName,
					origDir.Replace(':', Path.DirectorySeparatorChar), (string)file.get("name")));
				FileInfo fi = new FileInfo(fullName);
				fi.Delete();
			}
		}


	}
}
